<template>
  <div class="setting-wrap">
    <template v-if="!model">
      <span class="mr16">每</span>
      <el-select
        v-if="form.type === 'Minute'"
        v-model="form.minute"
        placeholder="请选择"
        class="mr16"
        :disabled="disabled"
        @change="onChange"
      >
        <el-option v-for="item in minuteList" :key="item" :label="item" :value="item" />
      </el-select>
      <el-select v-model="form.type" placeholder="请选择" class="mr16" :disabled="disabled" @change="onChange">
        <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
      </el-select>
      <span v-if="['Hour', 'Day', 'Week', 'Month', 'Year'].includes(form.type)" class="mr16">的</span>
      <el-select
        v-if="['Year'].includes(form.type)"
        v-model="form.month"
        placeholder="请选择"
        class="mr16"
        :disabled="disabled"
        @change="onChange"
      >
        <el-option v-for="item in monthList" :key="item.value" :label="item.label" :value="item.value" />
      </el-select>
      <el-select
        v-if="['Month', 'Year'].includes(form.type)"
        v-model="form.day"
        placeholder="请选择"
        class="mr16"
        :disabled="disabled"
        @change="onChange"
      >
        <el-option v-for="item in dayList" :key="item.value" :label="item.label" :value="item.value" />
      </el-select>
      <el-select
        v-if="['Week'].includes(form.type)"
        v-model="form.weekDay"
        placeholder="请选择"
        class="mr16"
        :disabled="disabled"
        @change="onChange"
      >
        <el-option v-for="item in weekDayList" :key="item.value" :label="item.label" :value="item.value" />
      </el-select>
      <el-select
        v-if="['Day', 'Week', 'Month', 'Year'].includes(form.type)"
        v-model="form.hour"
        placeholder="请选择"
        class="mr16"
        :disabled="disabled"
        @change="onChange"
      >
        <el-option v-for="item in hourList" :key="item.value" :label="item.label" :value="item.value" />
      </el-select>
      <el-select
        v-if="['Hour', 'Day', 'Week', 'Month', 'Year'].includes(form.type)"
        v-model="form.minute"
        placeholder="请选择"
        class="mr16"
        :disabled="disabled"
        @change="onChange"
      >
        <el-option v-for="item in minuteList2" :key="item.value" :label="item.label" :value="item.value" />
      </el-select>
    </template>
    <el-input v-else class="mr16" :value="value" :disabled="disabled" @input="$emit('input', $event)"></el-input>
    <el-checkbox v-model="model">手动输入</el-checkbox>
  </div>
</template>
<script>
export default {
  name: 'Expression',
  props: {
    value: {
      type: [Number, String],
      default: '',
    },
    disabled: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      model: false,
      options: [
        { label: '分钟', value: 'Minute' },
        { label: '小时', value: 'Hour' },
        { label: '天', value: 'Day' },
        { label: '周', value: 'Week' },
        { label: '月', value: 'Month' },
        { label: '年', value: 'Year' },
      ],
      form: {},
      minuteList: Array(60 - 10)
        .fill(0)
        .map((item, index) => 10 + index),
      minuteList2: Array(60)
        .fill(0)
        .map((item, index) => ({ label: (index / 10 >= 1 ? index : '0' + index) + ' 分', value: index })),
      hourList: Array(24)
        .fill(0)
        .map((item, index) => ({ label: (index / 10 >= 1 ? index : '0' + index) + ' 时', value: index })),
      weekDayList: [
        { label: '星期天', value: 1 },
        { label: '星期一', value: 2 },
        { label: '星期二', value: 3 },
        { label: '星期三', value: 4 },
        { label: '星期四', value: 5 },
        { label: '星期五', value: 6 },
        { label: '星期六', value: 7 },
      ],
      dayList: Array(31)
        .fill(0)
        .map((item, index) => ({
          label: ((index + 1) / 10 >= 1 ? index + 1 : '0' + (index + 1)) + ' 日',
          value: index + 1,
        })),
      monthList: Array(12)
        .fill(0)
        .map((item, index) => ({
          label: ((index + 1) / 10 >= 1 ? index + 1 : '0' + (index + 1)) + ' 月',
          value: index + 1,
        })),
    }
  },
  watch: {
    value: {
      handler: function (newval) {
        if (newval) {
          this.init()
        }
      },
      immediate: true,
    },
  },
  methods: {
    getCronExpressionByPartition() {
      switch (this.form.type) {
        case 'Minute':
          return `0 */${this.form.minute || 0} * * * ?`
        case 'Hour':
          return `0 ${this.form.minute || 0} * * * ?`
        case 'Day':
          return `0 ${this.form.minute || 0} ${this.form.hour || 0} * * ?`
        case 'Week':
          return `0 ${this.form.minute || 0} ${this.form.hour || 0} ? * ${this.form.weekDay || 0}`
        case 'Month':
          return `0 ${this.form.minute || 0} ${this.form.hour || 0} ${this.form.day || 0} * ?`
        case 'Year':
          return `0 ${this.form.minute || 0} ${this.form.hour || 0} ${this.form.day || 0} ${this.form.month || 0} ?`
        default:
          return '0 */10 * * * ?'
      }
    },
    onChange() {
      let expression = this.getCronExpressionByPartition()
      this.$emit('input', expression)
    },
    computePeriodUnit(cronExpression) {
      const partitions = cronExpression.split(' ')
      const stars = partitions.filter((item) => item === '*').length
      switch (stars) {
        case 3:
          return partitions[1].includes('/') ? 'Minute' : 'Hour'
        case 2:
          return 'Day'
        case 1:
          return partitions[partitions.length - 1] === '?' ? 'Month' : 'Week'
        case 0:
          return 'Year'
        default:
          return 'Minute'
      }
    },
    getTimeValues(cronExpression) {
      const partitions = cronExpression.split(' ')
      const currentPeriodUnit = this.computePeriodUnit(cronExpression)
      let minute = +((partitions[1] || []).includes('/')
        ? partitions[1].slice(2) // slice(2) to remove */
        : partitions[1])
      // min minute duration is 10
      if (currentPeriodUnit === 'Minute' && minute < 10) {
        minute = 10
      }
      const hour = +partitions[2] || 0
      const day = +partitions[3] || 1
      const month = +partitions[4] || 1
      const weekDay = +partitions[5] || 1
      return { minute, hour, day, month, weekDay, type: currentPeriodUnit }
    },
    init() {
      this.form = this.getTimeValues(this.value)
    },
  },
}
</script>
<style lang="scss" scoped>
.setting-wrap {
  display: flex;
  align-items: center;
}

.avue-form .el-select {
  width: 120px !important;
}

.el-input {
  max-width: calc(50% - 180px);
}

.mr16 {
  margin-right: 16px;
}
</style>
